#!/bin/sh

########################################################################
# This test checks if the provider module is unloadable while the target
# is in memory.
# 
# Usage: 
#   sh test_unload.sh <test_module>
#
# The test expects to find the test module (provider) in the subdirectory
# with the same name as that module.
########################################################################

# Just in case the tools like lsmod are not in their usual location.
export PATH=$PATH:/sbin:/bin:/usr/bin

########################################################################
# A function to check prerequisites: whether the necessary files exist,
# etc.
########################################################################
checkPrereqs()
{
    if test ! -f "${CORE_MODULE}"; then
        printf "The core module is missing: ${CORE_MODULE}\n"
        exit 1
    fi
    
    if test ! -f "${TEST_MODULE}"; then
        printf "The test module is missing: ${TEST_MODULE}\n"
        exit 1
    fi
    
    if test ! -f "${TARGET_MODULE}"; then
        printf "The target module is missing: ${TARGET_MODULE}\n"
        exit 1
    fi
}

########################################################################
# Cleanup function
########################################################################
cleanupAll()
{
    cd "${WORK_DIR}"
    
    lsmod | grep "${TARGET_MODULE_NAME}" > /dev/null 2>&1
    if test $? -eq 0; then
        rmmod "${TARGET_MODULE_NAME}"
    fi
    
    lsmod | grep "${TEST_MODULE_NAME}" > /dev/null 2>&1
    if test $? -eq 0; then
        rmmod "${TEST_MODULE_NAME}"
    fi
    
    lsmod | grep "${CORE_MODULE_NAME}" > /dev/null 2>&1
    if test $? -eq 0; then
        rmmod "${CORE_MODULE_NAME}"
    fi
}

########################################################################
# doTest() - perform the actual testing
########################################################################
doTest()
{
    insmod "${CORE_MODULE}" \
        targets="${TARGET_MODULE_NAME}" || exit 1

    insmod "${TEST_MODULE}"
    if test $? -ne 0; then
        printf "Failed to load the test module\n"
        cleanupAll
        exit 1
    fi
    
    insmod "${TARGET_MODULE}"
    if test $? -ne 0; then
        printf "Failed to load the target module: ${TARGET_MODULE_NAME}\n"
        cleanupAll
        exit 1
    fi

    # Check that the module providing the callbacks ("test module") can not 
    # be unloaded when the target is in memory.
    printf "The following 'rmmod' command is expected to fail.\n"
    rmmod "${TEST_MODULE_NAME}"
    if test $? -eq 0; then
        printf "The test module (the owner of the callbacks) "
        printf "should have been locked by the core for the time the "
        printf "target module is in memory. It seems, it was not locked "
        printf "because the test was able to unload the test module.\n"
        cleanupAll
        exit 1
    fi
    printf "The error above was expected, continuing the test...\n"
    
    rmmod "${TARGET_MODULE_NAME}"
    if test $? -ne 0; then
        printf "Failed to unload the target module: ${TARGET_MODULE_NAME}\n"
        cleanupAll
        exit 1
    fi

    rmmod "${TEST_MODULE_NAME}"
    if test $? -ne 0; then
        printf "Failed to unload the test module: ${TEST_MODULE_NAME}\n"
        cleanupAll
        exit 1
    fi

    rmmod "${CORE_MODULE_NAME}" || exit 1
}

########################################################################
# main
########################################################################
WORK_DIR=${PWD}

if test $# -ne 1; then
    printf "Usage:\n\tsh $0 <test_module>\n"
    exit 1
fi

CORE_MODULE_NAME="@CORE_MODULE_NAME@"
CORE_MODULE="@CORE_MODULE_DIR@/${CORE_MODULE_NAME}.ko"

TEST_MODULE_NAME="$1"
TEST_MODULE="${TEST_MODULE_NAME}/${TEST_MODULE_NAME}.ko"

TARGET_MODULE_NAME="kedr_sample_target"
TARGET_MODULE="@CMAKE_BINARY_DIR@/tests/sample_target/${TARGET_MODULE_NAME}.ko"

checkPrereqs

printf "Core module: ${CORE_MODULE}\n"
printf "Test module: ${TEST_MODULE}\n"
printf "Target module: ${TARGET_MODULE}\n"

doTest

# just in case
cleanupAll

# test passed
exit 0
